/*
 * Copyright (C) 2011, EADS France
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */

package xowl.generator;

/**
 *
 * @author Laurent WOUTERS
 */
public abstract class JavaDatatype {
    // XML Schema datatypes
    // Numeric datatypes
    public static final String xsdByte = "http://www.w3.org/2001/XMLSchema#byte";
    public static final String xsdUnsigedByte = "http://www.w3.org/2001/XMLSchema#unsignedByte";
    public static final String xsdShort = "http://www.w3.org/2001/XMLSchema#short";
    public static final String xsdUnsignedShort = "http://www.w3.org/2001/XMLSchema#unsignedShort";
    public static final String xsdInt = "http://www.w3.org/2001/XMLSchema#int";
    public static final String xsdInteger = "http://www.w3.org/2001/XMLSchema#integer";
    public static final String xsdUnsignedInteger = "http://www.w3.org/2001/XMLSchema#unsignedInt";
    public static final String xsdNonNegativeInteger = "http://www.w3.org/2001/XMLSchema#nonNegativeInteger";
    public static final String xsdNonPositiveinteger = "http://www.w3.org/2001/XMLSchema#nonPositiveInteger";
    public static final String xsdPositiveInteger = "http://www.w3.org/2001/XMLSchema#positiveInteger";
    public static final String xsdNegativeInteger = "http://www.w3.org/2001/XMLSchema#negativeInteger";
    public static final String xsdLong = "http://www.w3.org/2001/XMLSchema#long";
    public static final String xsdUnsignedLong = "http://www.w3.org/2001/XMLSchema#unsignedLong";
    public static final String xsdDouble = "http://www.w3.org/2001/XMLSchema#double";
    public static final String xsdFloat = "http://www.w3.org/2001/XMLSchema#float";
    public static final String xsdDecimal = "http://www.w3.org/2001/XMLSchema#decimal";
    // Boolean
    public static final String xsdBoolean = "http://www.w3.org/2001/XMLSchema#boolean";
    // String
    public static final String xsdString = "http://www.w3.org/2001/XMLSchema#string";
    // Date and times
    public static final String xsdDate = "http://www.w3.org/2001/XMLSchema#date";
    public static final String xsdDateTime = "http://www.w3.org/2001/XMLSchema#dateTime";
    public static final String xsdDuration = "http://www.w3.org/2001/XMLSchema#duration";
    public static final String xsdTime = "http://www.w3.org/2001/XMLSchema#time";
    // RDF Datatypes
    public static final String rdfPlainLiteral = "http://www.w3.org/1999/02/22-rdf-syntax-ns#PlainLiteral";
    // OWL Datatypes
    public static final String owlReal = "http://www.w3.org/2002/07/owl#real";
    public static final String owlRational = "http://www.w3.org/2002/07/owl#rational";


    protected xowl.lang.runtime.Datatype oWLDatatype;
    protected String oWLIRI;
    protected String javaType;

    public xowl.lang.runtime.Datatype getOWLDatatype() { return oWLDatatype; }
    public String getOWLIRI() { return oWLIRI; }
    public String getJavaType() { return javaType; }
    public abstract String getToString(String expression);
    public abstract String getToValue(String expression);
    public JavaDatatype(xowl.lang.runtime.Datatype owlDatatype, String owlIRI, String javaType) {
        this.oWLDatatype = owlDatatype;
        this.oWLIRI = owlIRI;
        this.javaType = javaType;
    }

    public static class DatatypeByte extends JavaDatatype {
        public DatatypeByte(xowl.lang.runtime.Datatype owlDatatype, String owlIRI) { super(owlDatatype, owlIRI, "java.lang.Byte"); }
        @Override public String getToString(String expression) { return expression + ".toString()"; }
        @Override public String getToValue(String expression) { return "java.lang.Byte.valueOf(" + expression + ")"; }
    }
    public static class DatatypeShort extends JavaDatatype {
        public DatatypeShort(xowl.lang.runtime.Datatype owlDatatype, String owlIRI) { super(owlDatatype, owlIRI, "java.lang.Short"); }
        @Override public String getToString(String expression) { return expression + ".toString()"; }
        @Override public String getToValue(String expression) { return "java.lang.Short.valueOf(" + expression + ")"; }
    }
    public static class DatatypeInteger extends JavaDatatype {
        public DatatypeInteger(xowl.lang.runtime.Datatype owlDatatype, String owlIRI) { super(owlDatatype, owlIRI, "java.lang.Integer"); }
        @Override public String getToString(String expression) { return expression + ".toString()"; }
        @Override public String getToValue(String expression) { return "java.lang.Integer.valueOf(" + expression + ")"; }
    }
    public static class DatatypeLong extends JavaDatatype {
        public DatatypeLong(xowl.lang.runtime.Datatype owlDatatype, String owlIRI) { super(owlDatatype, owlIRI, "java.lang.Long"); }
        @Override public String getToString(String expression) { return expression + ".toString()"; }
        @Override public String getToValue(String expression) { return "java.lang.Long.valueOf(" + expression + ")"; }
    }
    public static class DatatypeFloat extends JavaDatatype {
        public DatatypeFloat(xowl.lang.runtime.Datatype owlDatatype, String owlIRI) { super(owlDatatype, owlIRI, "java.lang.Float"); }
        @Override public String getToString(String expression) { return expression + ".toString()"; }
        @Override public String getToValue(String expression) { return "java.lang.Float.valueOf(" + expression + ")"; }
    }
    public static class DatatypeDouble extends JavaDatatype {
        public DatatypeDouble(xowl.lang.runtime.Datatype owlDatatype, String owlIRI) { super(owlDatatype, owlIRI, "java.lang.Double"); }
        @Override public String getToString(String expression) { return expression + ".toString()"; }
        @Override public String getToValue(String expression) { return "java.lang.Double.valueOf(" + expression + ")"; }
    }
    public static class DatatypeBoolean extends JavaDatatype {
        public DatatypeBoolean(xowl.lang.runtime.Datatype owlDatatype, String owlIRI) { super(owlDatatype, owlIRI, "java.lang.Boolean"); }
        @Override public String getToString(String expression) { return expression + ".toString()"; }
        @Override public String getToValue(String expression) { return "java.lang.Boolean.valueOf(" + expression + ")"; }
    }
    public static class DatatypeString extends JavaDatatype {
        public DatatypeString(xowl.lang.runtime.Datatype owlDatatype, String owlIRI) { super(owlDatatype, owlIRI, "java.lang.String"); }
        @Override public String getToString(String expression) { return expression; }
        @Override public String getToValue(String expression) { return expression; }
    }
    public static class DatatypeDate extends JavaDatatype {
        public DatatypeDate(xowl.lang.runtime.Datatype owlDatatype, String owlIRI) { super(owlDatatype, owlIRI, "java.util.Date"); }
        @Override public String getToString(String expression) { return expression + ".toString()"; }
        @Override public String getToValue(String expression) { return expression; }
    }


    private static final java.util.Map<String, java.lang.Class> mapDatatypes = new java.util.HashMap<String, java.lang.Class>();
    static {
        mapDatatypes.put(xsdByte, DatatypeByte.class);
        mapDatatypes.put(xsdUnsigedByte, DatatypeByte.class);
        mapDatatypes.put(xsdShort, DatatypeShort.class);
        mapDatatypes.put(xsdUnsignedShort, DatatypeShort.class);
        mapDatatypes.put(xsdInt, DatatypeInteger.class);
        mapDatatypes.put(xsdInteger, DatatypeInteger.class);
        mapDatatypes.put(xsdUnsignedInteger, DatatypeInteger.class);
        mapDatatypes.put(xsdNonNegativeInteger, DatatypeInteger.class);
        mapDatatypes.put(xsdNonPositiveinteger, DatatypeInteger.class);
        mapDatatypes.put(xsdPositiveInteger, DatatypeInteger.class);
        mapDatatypes.put(xsdNegativeInteger, DatatypeInteger.class);
        mapDatatypes.put(xsdLong, DatatypeLong.class);
        mapDatatypes.put(xsdUnsignedLong, DatatypeLong.class);
        mapDatatypes.put(xsdDouble, DatatypeDouble.class);
        mapDatatypes.put(xsdFloat, DatatypeFloat.class);
        mapDatatypes.put(xsdDecimal, DatatypeDouble.class);
        mapDatatypes.put(xsdBoolean, DatatypeBoolean.class);
        mapDatatypes.put(xsdString, DatatypeString.class);
        mapDatatypes.put(xsdDate, DatatypeDate.class);
        mapDatatypes.put(xsdDateTime, DatatypeDate.class);
        mapDatatypes.put(xsdDuration, DatatypeDate.class);
        mapDatatypes.put(xsdTime, DatatypeDate.class);

        mapDatatypes.put(owlReal, DatatypeDouble.class);
        mapDatatypes.put(owlRational, DatatypeDouble.class);
        mapDatatypes.put(rdfPlainLiteral, DatatypeString.class);
    }

    public static JavaDatatype createJavaDatatype(xowl.lang.runtime.Datatype datatype) {
        String iri = null;
        if (datatype == null)
            iri = xsdString;
        else
            iri = datatype.getInterpretationOf().getHasIRI().getHasValue();
        java.lang.Class datatypeClass = mapDatatypes.get(iri);
        JavaDatatype javaDatatype = null;
        try {
            java.lang.reflect.Constructor constructor = datatypeClass.getConstructor(xowl.lang.runtime.Datatype.class, String.class);
            javaDatatype = (JavaDatatype)constructor.newInstance(datatype, iri);
        } catch (java.lang.Exception ex) { }
        return javaDatatype;
    }
}
